package com.zhuliwei.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhuliwei.constants.SystemConstants;
import com.zhuliwei.domain.ResponseResult;
import com.zhuliwei.domain.dto.ChangeRoleStatusDto;
import com.zhuliwei.domain.dto.RoleAddDto;
import com.zhuliwei.domain.dto.RoleDto;
import com.zhuliwei.domain.entity.Role;
import com.zhuliwei.domain.entity.RoleMenu;
import com.zhuliwei.domain.vo.PageVo;
import com.zhuliwei.domain.vo.RoleVo;
import com.zhuliwei.enums.AppHttpCodeEnum;
import com.zhuliwei.exception.SystemException;
import com.zhuliwei.service.RoleMenuService;
import com.zhuliwei.service.RoleService;
import com.zhuliwei.utils.BeanCopyUtils;
import com.zhuliwei.utils.WebUtils;
import io.swagger.annotations.Api;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 角色管理接口控制层
 *
 * @author 朱力维
 * @time 2022/10/28 11:07
 **/
@RestController
@RequestMapping("/system/role")
@Api(tags = "角色", description = "角色管理相关接口")
public class RoleController {
    @Resource
    private RoleService roleService;

    @Resource
    private RoleMenuService roleMenuService;

    @GetMapping("/list")
    @PreAuthorize("@ps.hasPermission('system:role:list')")
    public ResponseResult<PageVo> list(Integer pageNum, Integer pageSize, RoleDto roleDto) {
        return roleService.rolePageList(pageNum, pageSize, roleDto);
    }

    @GetMapping("/listAllRole")
    public ResponseResult listAllRole() {
        LambdaQueryWrapper<Role> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Role::getStatus,SystemConstants.STATUS_NORMAL);
        List<Role> roles = roleService.list(lqw);
        // 集合在遍历的过程中不可以删除元素所以使用过滤器
        roles = roles.stream()
                .filter(role-> !role.getId().equals(SystemConstants.TYPE_ADMIN))
                .collect(Collectors.toList());
        return ResponseResult.okResult(roles);
    }

    @PutMapping("/changeStatus")
    @PreAuthorize("@ps.hasPermission('system:role:status')")
    public ResponseResult changeStatus(@RequestBody ChangeRoleStatusDto roleDto) {
        if (roleDto.getRoleId().equals(SystemConstants.TYPE_ADMIN)) {
            throw new SystemException(AppHttpCodeEnum.ADMIN_STOP_ERROR);
        }
        Role role = roleService.getById(roleDto.getRoleId());
        role.setStatus(roleDto.getStatus());
        roleService.updateById(role);
        return ResponseResult.okResult();
    }

    @DeleteMapping("/{ids}")
    @Transactional
    @PreAuthorize("@ps.hasPermission('system:role:delete')")
    public ResponseResult deleteRole(@PathVariable List<String> ids) {
        if (ids.contains(SystemConstants.TYPE_ADMIN)) {
            throw new SystemException(AppHttpCodeEnum.ADMIN_REMOVE_ERROR);
        }
        roleService.removeByIds(ids);
        for (String id:ids
             ) {
            LambdaQueryWrapper<RoleMenu> lqw = new LambdaQueryWrapper<>();
            lqw.eq(RoleMenu::getRoleId,id);
            roleMenuService.remove(lqw);
        }
        return ResponseResult.okResult();
    }

    @PostMapping
    @Transactional
    @PreAuthorize("@ps.hasPermission('system:role:add')")
    public ResponseResult add(@RequestBody RoleAddDto roleAddDto) {
        Role role = BeanCopyUtils.copyBean(roleAddDto, Role.class);
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        role.setId(uuid);
        roleService.save(role);
        List<RoleMenu> roleMenus = roleAddDto.getMenuIds().stream().map(menuId -> {
            return new RoleMenu(uuid, menuId);
        }).collect(Collectors.toList());
        roleMenuService.saveBatch(roleMenus);
        return ResponseResult.okResult();
    }

    @GetMapping("/{id}")
    public ResponseResult detail(@PathVariable String id) {
        if (id.equals(SystemConstants.TYPE_ADMIN)) {
            throw new SystemException(AppHttpCodeEnum.ADMIN_UPDATE_ERROR);
        }
        Role role = roleService.getById(id);
        return ResponseResult.okResult(role);
    }

    @PutMapping
    @Transactional
    @PreAuthorize("@ps.hasPermission('system:role:update')")
    public ResponseResult update(@RequestBody RoleAddDto roleAddDto) {
        LambdaQueryWrapper<RoleMenu> roleMenuLqw = new LambdaQueryWrapper<>();
        roleMenuLqw.eq(RoleMenu::getRoleId,roleAddDto.getId());
        roleMenuService.remove(roleMenuLqw);
        Role role = BeanCopyUtils.copyBean(roleAddDto, Role.class);
        roleService.updateById(role);
        List<RoleMenu> roleMenus = roleAddDto.getMenuIds().stream().map(menuId -> {
            return new RoleMenu(roleAddDto.getId(), menuId);
        }).collect(Collectors.toList());
        roleMenuService.saveBatch(roleMenus);
        return ResponseResult.okResult();
    }

    @GetMapping("/export")
    @PreAuthorize("@ps.hasPermission('system:role:export')")
    public void export(HttpServletResponse response) {
        try {
            //设置下载文件的请求头
            WebUtils.setDownLoadHeader("角色.xlsx", response);
            //获取需要导出的数据
            List<Role> roles = roleService.list();
            List<RoleVo> RoleVos = BeanCopyUtils.copyBeanList(roles, RoleVo.class);
            //把数据写入到Excel中
            EasyExcel.write(response.getOutputStream(), RoleVo.class).autoCloseStream(Boolean.FALSE).sheet("角色导出")
                    .doWrite(RoleVos);

        } catch (Exception e) {
            //如果出现异常也要响应json
            ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR);
            WebUtils.renderString(response, JSON.toJSONString(result));
        }
    }

}
